import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import math
import json
import pyperclip
import time
import re
from data_loader import data, base_materials, id_to_name, all_item_ids, get_crafting_helper
from collections import defaultdict
from global_calculator import CraftingCalculator, BaseMaterialEditor
from settings_applier import apply_settings

class TextResultWindow(tk.Toplevel):
    """可复用的文本结果显示窗口"""
    def __init__(self, parent, title, content, filename_base=None,settings=None):
        super().__init__(parent)
        self.settings = settings or {}
        self.apply_settings(self.settings)
        self.title(title)
        self.geometry("770x600")
        self.filename_base = filename_base or title
        
        # 主框架
        main_frame = ttk.Frame(self)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 文本显示区域
        text_frame = ttk.Frame(main_frame)
        text_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        # 创建文本框
        self.text = tk.Text(
            text_frame, 
            wrap=tk.WORD, 
            font=("Consolas", 10),
            background=self.settings['background_color']
        )
        self.text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 定义滑动条
        vsb = ttk.Scrollbar(text_frame, command=self.text.yview)
        vsb.pack(side=tk.RIGHT, fill=tk.Y)
        self.text.configure(yscrollcommand=vsb.set)
        
        self.text.insert(tk.END, content)
        self.text.config(state=tk.DISABLED)
        
        # 按钮区域
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(pady=10)
        
        ttk.Button(
            btn_frame, 
            text="复制到剪贴板", 
            command=lambda: self.copy_to_clipboard(content)
        ).pack(side=tk.LEFT, padx=5)
        
        ttk.Button(
            btn_frame, 
            text="保存到文件", 
            command=lambda: self.save_to_file(content)
        ).pack(side=tk.LEFT, padx=5)
    
    def apply_settings(self, settings):
        """应用设置到当前窗口"""
        apply_settings(self, settings)

    def copy_to_clipboard(self, text):
        """复制文本到剪贴板"""
        try:
            pyperclip.copy(text)
            messagebox.showinfo("复制成功", "内容已复制到剪贴板")
        except Exception as e:
            messagebox.showerror("复制失败", f"无法复制到剪贴板: {str(e)}")
    
    def save_to_file(self, text):
        """保存文本到文件"""
        safe_name = "".join(c if c.isalnum() or c in " -_" else "_" for c in self.filename_base)
        filename = f"{safe_name}.txt"
        
        file_path = filedialog.asksaveasfilename(
            initialfile=filename,
            defaultextension=".txt",
            filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
        
        try:
            with open(file_path, "w", encoding="utf-8") as f:
                f.write(text)
            messagebox.showinfo("保存成功", f"文件已保存到:\n{file_path}")
        except Exception as e:
            messagebox.showerror("保存失败", f"保存文件时出错:\n{str(e)}")


class CraftingRouteWindow(tk.Toplevel):
    """图文模式的合成路线窗口"""
    def __init__(self, parent, item_id, quantity, result,settings=None):
        super().__init__(parent)
        self.parent = parent
        self.item_id = item_id
        self.quantity = quantity
        self.result = result
        self.settings = settings or {}
        self.apply_settings(self.settings)
        
        # 修复：反转合成步骤顺序
        if "madeRoute" in result:
            self.made_route = result["madeRoute"][::-1]  # 关键修复：反转顺序
        else:
            self.made_route = []
        
        # 计算总步数
        self.total_steps = len(self.made_route) + 1  # +1 包括第0步
        self.current_step = 0
        
        self.title("合成路线(图文)")
        self.geometry("800x700")
        self.transient(parent)
        
        # 创建主框架
        self.main_frame = ttk.Frame(self)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 标题栏
        self.title_frame = ttk.Frame(self.main_frame)
        self.title_frame.pack(fill=tk.X, pady=5)
        
        self.step_label = ttk.Label(self.title_frame, text="", font=("Arial", 12, "bold"))
        self.step_label.pack()
        
        # 内容框架
        self.content_frame = ttk.Frame(self.main_frame)
        self.content_frame.pack(fill=tk.BOTH, expand=True, pady=10)
        
        # 图像占位符框架
        self.image_frame = ttk.LabelFrame(self.content_frame, text="合成示意图")
        self.image_frame.pack(fill=tk.X, pady=5)
        self.image_placeholder = ttk.Label(
            self.image_frame, 
            text="(此处将显示合成示意图)",
            font=("Arial", 10, "italic"),
            foreground="gray",
            anchor=tk.CENTER,
            padding=20
        )
        self.image_placeholder.pack(fill=tk.BOTH, expand=True)
        
        # 文字描述区域
        self.text_frame = ttk.LabelFrame(self.content_frame, text="步骤详情")
        self.text_frame.pack(fill=tk.BOTH, expand=True, pady=5)
        
        # 创建滚动条框架
        self.text_scroll_frame = ttk.Frame(self.text_frame)
        self.text_scroll_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 创建滚动条
        self.text_scrollbar = ttk.Scrollbar(self.text_scroll_frame)
        self.text_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建文本框并与滚动条关联
        self.text_area = tk.Text(
            self.text_scroll_frame, 
            wrap=tk.WORD, 
            height=10,
            font=("Consolas", 10),
            state=tk.DISABLED,
            yscrollcommand=self.text_scrollbar.set,
            background=self.settings['background_color']
        )
        self.text_area.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 设置滚动条命令
        self.text_scrollbar.config(command=self.text_area.yview)
        
        # 按钮区域
        self.button_frame = ttk.Frame(self.main_frame)
        self.button_frame.pack(fill=tk.X, pady=10)
        
        self.prev_button = ttk.Button(
            self.button_frame, 
            text="上一步", 
            command=self.prev_step,
            state=tk.DISABLED
        )
        self.prev_button.pack(side=tk.LEFT, padx=5)
        
        self.next_button = ttk.Button(
            self.button_frame, 
            text="下一步", 
            command=self.next_step
        )
        self.next_button.pack(side=tk.RIGHT, padx=5)
        
        # 显示初始步骤
        self.show_step(0)
    
    def apply_settings(self, settings):
        """应用设置到当前窗口"""
        apply_settings(self, settings)

    def show_step(self, step_num):
        """显示指定步骤的内容"""
        self.current_step = step_num
        self.step_label.config(text=f"步骤 {step_num}/{self.total_steps-1}")
        
        # 更新按钮状态
        self.prev_button.config(state=tk.NORMAL if step_num > 0 else tk.DISABLED)
        self.next_button.config(state=tk.NORMAL if step_num < self.total_steps-1 else tk.DISABLED)
        
        # 清空文本区域
        self.text_area.config(state=tk.NORMAL)
        self.text_area.delete(1.0, tk.END)
        
        # 第0步：基础材料准备
        if step_num == 0:
            self.show_preparation_step()
        # 其他步骤：合成过程
        else:
            self.show_crafting_step(step_num - 1)
        
        self.text_area.config(state=tk.DISABLED)
    
    def show_preparation_step(self):
        """显示准备步骤（第0步）"""
        self.text_area.insert(tk.END, "准备材料:\n\n", "title")
        
        # 基础材料
        basic_materials = self.result.get("basicMaterial", [])
        if basic_materials:
            self.text_area.insert(tk.END, "所需基础材料:\n", "subtitle")
            
            # 合并相同材料
            material_dict = defaultdict(float)
            for mat in basic_materials:
                material_dict[mat["item"]] += mat["count"]
            
            item_number = 1
            for mat_id, amount in material_dict.items():
                mat_name = id_to_name.get(mat_id, mat_id)
                rounded_amount = math.ceil(amount)
                self.text_area.insert(
                    tk.END, 
                    f" [{item_number}]. {mat_name}: {CraftingCalculator.format_quantity(rounded_amount)}\n"
                )
                item_number+=1
        else:
            self.text_area.insert(tk.END, "无基础材料\n")
        
        # 剩余材料
        excess_materials = defaultdict(float)
        if self.result.get("extraItem"):
            for item in self.result["extraItem"]:
                excess_materials[item["item"]] += item["count"]
        
        if excess_materials:
            self.text_area.insert(tk.END, "\n预计剩余材料:\n", "subtitle")
            for mat_id, count in excess_materials.items():
                mat_name = id_to_name.get(mat_id, mat_id)
                rounded_count = math.ceil(count)
                self.text_area.insert(
                    tk.END, 
                    f"  - {mat_name}: {CraftingCalculator.format_quantity(rounded_count)}\n"
                )
        else:
            self.text_area.insert(tk.END, "\n无剩余材料\n")
        
        # 配置文本样式
        self.text_area.tag_configure("title", font=("Arial", 11, "bold"))
        self.text_area.tag_configure("subtitle", font=("Arial", 10, "bold"))
        
        # 更新图像占位符
        self.image_placeholder.config(
            text=f"准备制作 {self.quantity}个 {id_to_name.get(self.item_id, self.item_id)}\n所需基础材料"
        )
    
    def show_crafting_step(self, step_index):
        """显示合成步骤"""
        # 使用反转后的步骤列表
        step = self.made_route[step_index]
        
        # 显示步骤标题
        self.text_area.insert(tk.END, f"步骤 {step_index+1}:\n\n", "title")
        
        # 构建输入材料字符串
        input_materials = []
        for item, count in step["materialList"]:
            mat_name = id_to_name.get(item, item)
            rounded_count = math.ceil(count)
            input_materials.append(f"{mat_name} × {CraftingCalculator.format_quantity(rounded_count)}")
        
        # 构建输出结果字符串
        product_name = id_to_name.get(step["product"], step["product"])
        product_count = math.ceil(step["productCount"])
        output_str = f"{product_name} × {CraftingCalculator.format_quantity(product_count)}"
        
        # 显示完整的合成公式
        self.text_area.insert(tk.END, "合成配方:\n", "subtitle")
        formula = " + ".join(input_materials)
        formula += f" ==({step['machine']})=> {output_str}"
        self.text_area.insert(tk.END, formula + "\n\n")
        
        # 配置文本样式
        self.text_area.tag_configure("title", font=("Arial", 11, "bold"))
        self.text_area.tag_configure("subtitle", font=("Arial", 10, "bold"))
        
        # 更新图像占位符
        input_names = ', '.join([id_to_name.get(item, item) for item, _ in step["materialList"]])
        self.image_placeholder.config(
            text=f"步骤 {step_index+1}: {step['machine']}\n"
                f"输入: {input_names}\n"
                f"输出: {product_name}\n"
                "此功能未完成!"
        )
    
    def prev_step(self):
        """显示上一步"""
        if self.current_step > 0:
            self.show_step(self.current_step - 1)
    
    def next_step(self):
        """显示下一步"""
        if self.current_step < self.total_steps - 1:
            self.show_step(self.current_step + 1)


class ItemDetailWindow(tk.Toplevel):
    def __init__(self, master, item_id, is_primary=False, settings=None):
        super().__init__(master)
        self.settings = settings or {}
        self.apply_settings(self.settings)
        self.master = master
        self.item_id = item_id
        self.is_primary = is_primary
        self.history = [item_id]  # 初始化包含当前物品的历史记录
        self.current_index = 0
        self.quantity = 1  # 默认制作数量
        
        self.protocol("WM_DELETE_WINDOW", self.on_close)
        self.title("物品详情")
        self.geometry("600x700")
        self.transient(master)
        
        # 创建主框架
        self.main_frame = ttk.Frame(self)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 只在顶级窗口显示数量输入框
        if self.is_primary:
            self.create_quantity_frame()
        
        # 按钮区域
        self.create_button_frame()
        
        # 内容框架
        self.content_frame = None
        self.display_item(item_id)

    def apply_settings(self, settings):
        """应用设置到当前窗口"""
        apply_settings(self, settings)

    def create_quantity_frame(self):
        """创建制作数量输入区域 - 只在顶级窗口显示"""
        quantity_frame = ttk.Frame(self.main_frame)
        quantity_frame.pack(fill=tk.X, pady=5, padx=10)
        
        ttk.Label(quantity_frame, text="制作数量:").pack(side=tk.LEFT, padx=(0, 5))
        
        # 验证函数，只允许输入正整数
        def validate_input(new_value):
            if new_value == "":
                return True
            if re.match(r'^[1-9]\d*$', new_value):
                return True
            return False
        
        vcmd = (self.register(validate_input), '%P')
        
        self.quantity_var = tk.StringVar(value="1")
        self.quantity_entry = ttk.Entry(
            quantity_frame, 
            textvariable=self.quantity_var, 
            width=10,
            validate="key",
            validatecommand=vcmd
        )
        self.quantity_entry.pack(side=tk.LEFT)
        
        # 添加提示标签
        ttk.Label(quantity_frame, text="(正整数)", foreground="gray").pack(side=tk.LEFT, padx=(5, 0))
        
        # 绑定焦点离开事件，处理无效输入
        def on_focus_out(event):
            value = self.quantity_var.get()
            if not value or not value.isdigit() or int(value) < 1:
                self.quantity_var.set("1")
                messagebox.showwarning("输入错误", "制作数量必须是正整数，已重置为1")
        
        self.quantity_entry.bind("<FocusOut>", on_focus_out)

    def get_quantity(self):
        """获取并验证制作数量"""
        try:
            quantity = int(self.quantity_var.get())
            if quantity < 1:
                raise ValueError("数量必须大于0")
            return quantity
        except ValueError:
            self.quantity_var.set("1")
            messagebox.showwarning("输入错误", "制作数量必须是正整数，已重置为1")
            return 1
    
    def on_close(self):
        """窗口关闭时的处理"""
        self.destroy()
        if self.is_primary and self.master:
            self.master.deiconify()
    
    def create_button_frame(self):
        """创建按钮框架"""
        self.button_frame = ttk.Frame(self.main_frame)
        self.button_frame.pack(fill=tk.X, pady=5)
        
        # 次级窗口的按钮布局
        if not self.is_primary:
            # 返回按钮（左侧）
            self.back_button = ttk.Button(
                self.button_frame, 
                text="返回", 
                command=self.go_back,
                state=tk.DISABLED
            )
            self.back_button.pack(side=tk.LEFT)
            
            # 关闭按钮（右侧）
            ttk.Button(
                self.button_frame, 
                text="关闭", 
                command=self.destroy
            ).pack(side=tk.RIGHT)
        
        # 主窗口的按钮布局
        else:
            # 左侧功能按钮
            left_frame = ttk.Frame(self.button_frame)
            left_frame.pack(side=tk.LEFT, fill=tk.X, expand=True)
            
            buttons = [
                ("编辑基础材料", self.edit_base_materials),
                ("计算材料(列表)", self.calculate_materials_list),
                ("合成步骤", self.show_crafting_steps),
                ("合成路线(图文)", self.show_crafting_route)
            ]
            
            for text, command in buttons:
                ttk.Button(
                    left_frame, 
                    text=text, 
                    command=command
                ).pack(side=tk.LEFT, padx=5)
            
            # 右侧关闭按钮
            right_frame = ttk.Frame(self.button_frame)
            right_frame.pack(side=tk.RIGHT)
            
            ttk.Button(
                right_frame, 
                text="关闭", 
                command=self.destroy
            ).pack(side=tk.RIGHT, padx=5)
    
    def display_item(self, item_id):
        """显示指定物品的详情"""
        # 清除旧内容
        if self.content_frame:
            self.content_frame.destroy()
        
        # 创建新内容框架
        self.content_frame = ttk.Frame(self.main_frame)
        self.content_frame.pack(fill=tk.BOTH, expand=True)
        
        # 获取物品数据
        item = next((i for i in data if i["id"] == item_id), None)
        if not item:
            messagebox.showerror("错误", "找不到指定的物品")
            return
        
        # 更新窗口标题
        self.title(f"物品详情 - {item['name']}")
        
        # 显示基本信息
        self.create_info_frame(item)
        
        # 显示合成配方
        self.create_recipe_frame(item)
    
    def create_info_frame(self, item):
        """创建物品基本信息框架 - 可复制但不可修改"""
        info_frame = ttk.LabelFrame(self.content_frame, text="基本信息(可选择后右键复制)")
        info_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 创建只读文本控件
        text = tk.Text(
            info_frame, 
            height=5,  # 固定高度显示所有信息
            wrap=tk.WORD,
            font=("TkDefaultFont", 10),
            borderwidth=0,
            highlightthickness=0,
            padx=5,
            pady=5
        )
        text.pack(fill=tk.X, expand=True)
        
        # 构建信息内容
        info_items = [
            f"名称: {item['name']}",
            f"ID: {item['id']}",
            f"配方类型: {item['recipeType']}"
        ]
        
        if "output" in item:
            info_items.append(f"输出数量: {item['output']}")
        
        if "research" in item:
            research_info = f"研究项目: {item['research']}"
            if "researchCost" in item:
                research_info += f" | 消耗: {item['researchCost']}"
            info_items.append(research_info)
        
        # 插入内容并应用字体
        for i, line in enumerate(info_items):
            # 名称行加粗
            if i == 0:
                text.insert(tk.END, line + "\n", "bold")
            else:
                text.insert(tk.END, line + "\n")
        
        # 配置字体样式
        text.tag_configure("bold", font=("TkDefaultFont", 10, "bold"))
        
        # 设置为只读
        text.configure(state=tk.DISABLED)
    
    # 添加右键复制菜单
        def copy_text(event):
            if text.tag_ranges(tk.SEL):
                selected = text.get(tk.SEL_FIRST, tk.SEL_LAST)
                self.clipboard_clear()
                self.clipboard_append(selected)
        
        # 绑定右键菜单
        text.bind("<Button-3>", lambda e: copy_text(e))
    
    def create_recipe_frame(self, item):
        """创建合成配方框架"""
        recipe = item.get("recipe", [])
        recipe_size = 6 if len(recipe) > 9 else 3
        
        recipe_frame = ttk.LabelFrame(
            self.content_frame, 
            text=f"合成配方 ({recipe_size}×{recipe_size})"
        )
        recipe_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 10))
        
        # 配置网格布局
        for i in range(recipe_size):
            recipe_frame.columnconfigure(i, weight=1, uniform=f"col_{recipe_size}")
            recipe_frame.rowconfigure(i, weight=1, uniform=f"row_{recipe_size}")
        
        # 填充网格
        for idx in range(recipe_size * recipe_size):
            row_idx = idx // recipe_size
            col_idx = idx % recipe_size
            slot = recipe[idx] if idx < len(recipe) else None
            
            self.create_recipe_cell(recipe_frame, row_idx, col_idx, slot)
    
    def create_recipe_cell(self, parent, row, col, slot):
        """创建单个配方格子"""
        cell_frame = ttk.Frame(parent, borderwidth=1, relief="solid")
        cell_frame.grid(row=row, column=col, padx=2, pady=2, sticky="nsew")
        
        if not slot:
            bg = "#f0f0f0"
            text = " "
            clickable = False
        else:
            material_id = slot["material"]
            clickable = material_id in all_item_ids
            bg = "#a0c0ff" if clickable else "#e0f0ff"
            text = f"{slot['name']}\n({material_id})"
            if "amount" in slot:
                text += f"\n×{slot['amount']}"
        
        label = ttk.Label(
            cell_frame, 
            text=text, 
            background=bg, 
            anchor="center", 
            justify="center", 
            wraplength=150
        )
        label.pack(fill=tk.BOTH, expand=True, padx=2, pady=2)
        
        # 添加交互功能
        if clickable:
            label.bind("<Button-1>", lambda e, mat_id=material_id: self.on_material_click(mat_id))
            label.bind("<Enter>", lambda e, lbl=label: lbl.configure(background="#c0e0ff"))
            label.bind("<Leave>", lambda e, lbl=label, bg=bg: lbl.configure(background=bg))
    
    def on_material_click(self, material_id):
        """处理材料点击事件"""
        if self.is_primary:
            ItemDetailWindow(self.master, material_id,settings=self.settings)
        else:
            self.add_to_history(material_id)
    
    def add_to_history(self, item_id):
        """添加新物品到历史记录"""
        # 截断当前位置之后的历史
        if self.current_index < len(self.history) - 1:
            self.history = self.history[:self.current_index + 1]
        
        self.history.append(item_id)
        self.current_index = len(self.history) - 1
        self.update_navigation_buttons()
        self.display_item(item_id)
    
    def go_back(self):
        """返回上一个查看的物品"""
        if self.current_index > 0:
            self.current_index -= 1
            self.update_navigation_buttons()
            self.display_item(self.history[self.current_index])
    
    def update_navigation_buttons(self):
        """更新导航按钮状态"""
        if not self.is_primary:
            self.back_button.config(state=tk.NORMAL if self.current_index > 0 else tk.DISABLED)
    
    def edit_base_materials(self):
        """编辑基础材料名单"""
        BaseMaterialEditor(self, refresh_callback=self.refresh_current_item,settings=self.settings)
    
    def refresh_current_item(self):
        """刷新当前物品显示（基础材料更新后）"""
        self.display_item(self.item_id)
    
    def calculate_materials_list(self):
        """计算制作当前物品所需的所有基础材料"""
        start_time = time.perf_counter()
        quantity = self.get_quantity()
        
        # 使用共享的计算功能
        result, error = CraftingCalculator.calculate_materials({self.item_id: quantity})
        
        if error:
            messagebox.showerror("错误", error)
            return
        
        if not result.get("basicMaterial"):
            messagebox.showinfo("无基础材料", "该物品不需要任何基础材料")
            return
        
        # 格式化结果
        result_text = CraftingCalculator.format_material_list(result, {self.item_id: quantity})
        
        elapsed_time = time.perf_counter() - start_time
        time_str = f"生成耗时: {elapsed_time:.5f}秒"
        
        # 使用通用文本显示窗口
        TextResultWindow(
            self,
            f"制作 {quantity}个{id_to_name.get(self.item_id, self.item_id)}所需材料 [{time_str}]",
            result_text,
            f"{quantity}个{id_to_name.get(self.item_id, self.item_id)}_材料清单",
            settings=self.settings
        )
    
    def show_crafting_steps(self):
        """显示合成步骤，包括剩余材料"""
        start_time = time.perf_counter()
        quantity = self.get_quantity()
        
        # 使用共享的计算功能
        result, error = CraftingCalculator.calculate_materials({self.item_id: quantity})
        
        if error:
            messagebox.showerror("错误", error)
            return
        
        item_display_name = id_to_name.get(self.item_id, self.item_id)
        
        # 格式化结果
        output = CraftingCalculator.format_crafting_steps(result, {self.item_id: quantity})
        
        elapsed_time = time.perf_counter() - start_time
        time_str = f"生成耗时: {elapsed_time:.5f}秒"
        
        # 使用通用文本显示窗口
        TextResultWindow(
            self,
            f"{quantity}个{item_display_name}的合成步骤 [{time_str}]",
            output,
            f"{quantity}个{item_display_name}_合成步骤",
            settings=self.settings
        )
    
    def show_crafting_route(self):
        """显示图文模式的合成路线"""
        quantity = self.get_quantity()
        
        # 使用共享的计算功能
        result, error = CraftingCalculator.calculate_materials({self.item_id: quantity})
        
        if error:
            messagebox.showerror("错误", error)
            return
        
        # 检查是否有合成步骤
        if not result.get("madeRoute"):
            messagebox.showinfo("无合成步骤", "该物品没有合成步骤，可能是基础材料")
            return
        
        # 打开图文合成路线窗口
        CraftingRouteWindow(self, self.item_id, quantity, result,settings=self.settings)